home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
076-100
/
disk_092
/
as6502
/
assm2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
11KB
|
512 lines
#include "stdio.h"
#include "assm.d1"
#include "assm.d2"
#include "ctype.h"
extern int optab[];
extern int step[];
/* translate source line to machine language */
assemble()
{
int flg;
int i; /* prlnbuf pointer */
if ((prlnbuf[SFIELD] == ';') | (prlnbuf[SFIELD] == 0)) {
if (pass == LAST_PASS)
println();
return;
}
lablptr = -1;
i = SFIELD;
udtype = UNDEF;
if (colsym(&i) != 0 && (lablptr = stlook()) == -1)
return;
while (prlnbuf[++i] == ' '); /* find first non-space */
if ((flg = oplook(&i)) < 0) { /* collect operation code */
labldef(loccnt);
if (flg == -1)
error("Invalid operation code");
if ((flg == -2) && (pass == LAST_PASS)) {
if (lablptr != -1)
loadlc(loccnt, 1, 0);
println();
}
return;
}
if (opflg == PSEUDO)
pseudo(&i);
else if (labldef(loccnt) == -1)
return;
else {
if (opflg == CLASS1)
class1();
else if (opflg == CLASS2)
class2(&i);
else class3(&i);
}
}
/****************************************************************************/
/* printline prints the contents of prlnbuf */
println()
{
if (lflag > 0)
{
if (paglin == pagesize) printhead();
prlnbuf[linesize] = '\0';
fprintf(stdout, "%s\n", prlnbuf);
paglin++ ;
}
}
/****************************************************************************/
/* printhead prints the page heading */
printhead()
{
if (pagesize == 0) return;
pagect++ ;
fprintf(stdout, "\f\nAmiga 6502 assembler : - %s PAGE %d\n",
titlbuf,pagect);
fprintf(stdout, "Line Location Label Opcode Operand Comment %s\n\n",date);
paglin = 0;
}
/* colsym() collects a symbol from prlnbuf into symbol[],
* leaves prlnbuf pointer at first invalid symbol character,
* returns 0 if no symbol collected
*/
colsym(ip)
int *ip;
{
int valid;
int i;
char ch;
valid = 1;
i = 0;
while (valid == 1) {
ch = prlnbuf[*ip];
if (ch == '_' || ch == '.');
else if (ch >= 'a' && ch <= 'z');
else if (ch >= 'A' && ch <= 'Z');
else if (i >= 1 && ch >= '0' && ch <= '9');
else if (i == 1 && ch == '=');
else valid = 0;
if (valid == 1) {
if (i < SBOLSZ - 1)
symbol[++i] = ch;
(*ip)++;
}
}
if (i == 1) {
switch (symbol[1]) {
case 'A': case 'a':
case 'X': case 'x':
case 'Y': case 'y':
error("Symbol is reserved (A, X or Y)");
i = 0;
}
}
symbol[0] = i;
return(i);
}
/* symbol table lookup
* if found, return pointer to symbol
* else, install symbol as undefined, and return pointer
*/
stlook()
{
int ptr, ln, eq;
ptr = 0;
while (ptr < nxt_free)
{
ln = symbol[0]; if (symtab[ptr] < ln) ln = symtab[ptr];
if ((eq = strncmp(&symtab[ptr+1], &symbol[1], ln)) == 0 &&
symtab[ptr] == symbol[0]) return ptr;
if (eq > 0) return(stinstal(ptr));
ptr = ptr+6+ symtab[ptr];
ptr = ptr +1 + 2*(symtab[ptr] & 0xff);
}
return (stinstal(ptr));
}
/* instal symbol into symtab
*/
stinstal(ptr)
int ptr;
{
int ptr2, i;
if (openspc(ptr,symbol[0]+7) == -1) {
error("Symbol Table Full"); /* print error msg and ... */
pass = DONE; /* cause termination of assembly */
return -1; }
ptr2 = ptr;
for (i=0; i< symbol[0]+1; i++)
symtab[ptr2++] = symbol[i];
symtab[ptr2++] = udtype;
symtab[ptr2+4] = 0;
return(ptr);
}
/* addref : add a reference line to the symbol pointed to */
/* by ip. */
addref(ip)
int ip;
{
int rct, ptr;
rct = ptr =ip + symtab[ip] + 6;
if ((symtab[rct] & 0xff) == 255) { /* non-fatal error */
fprintf(stderr,"%s\n",prlnbuf);
fprintf(stderr,"Too many references\n");
return; }
ptr += (symtab[rct] & 0xff) * 2 +1;
if (openspc(ptr,2) == -1) {
error("Symbol Table Full");
return -1; }
symtab[ptr] = slnum & 0xff;
symtab[ptr+1] = (slnum >> 8) & 0xff;
symtab[rct]++;
}
/* openspc : open up a space in the symbol table */
/* the space will be at (ptr) and will be */
/* len characters long. return -1 if no room. */
openspc(ptr,len)
int ptr,len;
{
int ptr2, ptr3;
if (nxt_free + len > size) return -1;
if (ptr != nxt_free)
{
ptr2 = nxt_free -1;
ptr3 = ptr2 + len;
while (ptr2 >= ptr) symtab[ptr3--] = symtab[ptr2--];
}
nxt_free += len;
if (lablptr >= ptr) lablptr += len;
return 0;
}
/* operation code table lookup
* if found, return pointer to symbol,
* else, return -1
*/
oplook(ip)
int *ip;
{
register char ch;
register int i;
register int j;
int k;
int temp[2];
i = j = 0;
temp[0] = temp[1] = 0;
while((ch=prlnbuf[*ip])!= ' ' && ch!= 0 && ch!= '\t' && ch!= ';') {
if (ch >= 'A' && ch <= 'Z')
ch &= 0x1f;
else if (ch >= 'a' && ch <= 'z')
ch &= 0x1f;
else if (ch == '.')
ch = 31;
else if (ch == '*')
ch = 30;
else if (ch == '=')
ch = 29;
else return(-1);
temp[j] = (temp[j] * 0x20) + (ch & 0xff);
if (ch == 29)
break;
++(*ip);
if (++i >= 3) {
i = 0;
if (++j >= 2) {
return(-1);
}
}
}
if ((j = temp[0]^temp[1]) == 0)
return(-2);
k = 0;
i = step[k] - 3;
do {
if (j == optab[i]) {
opflg = optab[++i];
opval = optab[++i];
return(i);
}
else if (j < optab[i])
i -= step[++k];
else i += step[++k];
} while (step[k] != 0);
return(-1);
}
/* error printing routine */
error(stptr)
char *stptr;
{
loadlc(loccnt, 0, 1);
loccnt += 3;
loadv(0,0,0);
loadv(0,1,0);
loadv(0,2,0);
fprintf(stderr, "%s\n", prlnbuf);
fprintf(stderr, "%s\n", stptr);
errcnt++;
}
/* load 16 bit value in printable form into prlnbuf */
loadlc(val, f, outflg)
int val;
int f;
int outflg;
{
int i;
i = 6 + 7*f;
hexcon(4, val);
if (nflag == 0) {
prlnbuf[i++] = hex[3];
prlnbuf[i++] = hex[4];
prlnbuf[i++] = ':';
prlnbuf[i++] = hex[1];
prlnbuf[i] = hex[2];
}
else {
prlnbuf[i++] = hex[1];
prlnbuf[i++] = hex[2];
prlnbuf[i++] = hex[3];
prlnbuf[i] = hex[4];
}
if ((pass == LAST_PASS)&&(oflag != 0)&&(objcnt <= 0)&&(outflg != 0))
{
if (mflag != 0) start_obj(val);
else fprintf(optr, "\n;%c%c%c%c", hex[3], hex[4], hex[1], hex[2]);
objcnt=22;
}
}
/* load value in hex into prlnbuf[contents[i]] */
/* and output hex characters to obuf if LAST_PASS & oflag == 1 */
loadv(val,f,outflg)
int val;
int f; /* contents field subscript */
int outflg; /* flag to output object bytes */
{
hexcon(2, val);
prlnbuf[13 + 3*f] = hex[1];
prlnbuf[14 + 3*f] = hex[2];
if ((pass == LAST_PASS) && (oflag != 0) && (outflg != 0)) {
if (mflag != 0) put_obj(val);
else { fputc(hex[1], optr);
fputc(hex[2], optr); }
--objcnt;
}
}
/* convert number supplied as argument to hexadecimal in hex[digit] (lsd)
through hex[1] (msd) */
hexcon(digit, num)
int digit;
int num;
{
for (; digit > 0; digit--) {
hex[digit] = (num & 0x0f) + '0';
if (hex[digit] > '9')
hex[digit] += 'A' -'9' - 1;
num >>= 4;
}
}
/* assign <value> to label pointed to by lablptr,
* checking for valid definition, etc.
*/
labldef(lval)
int lval;
{
int i;
if (lablptr != -1) {
lablptr += symtab[lablptr] + 1;
if (pass == FIRST_PASS) {
if (symtab[lablptr] == UNDEF) {
symtab[lablptr + 1] = lval & 0xff;
i = symtab[lablptr + 2] = (lval >> 8) & 0xff;
if (i == 0)
symtab[lablptr] = DEFZRO;
else symtab[lablptr] = DEFABS;
}
else if (symtab[lablptr] == UNDEFAB) {
symtab[lablptr] = DEFABS;
symtab[lablptr + 1] = lval & 0xff;
symtab[lablptr + 2] = (lval >> 8) & 0xff;
}
else {
symtab[lablptr] = MDEF;
symtab[lablptr + 1] = 0;
symtab[lablptr + 2] = 0;
error("Label multiply defined");
return(-1);
}
symtab[lablptr+3] = slnum & 0xff;
symtab[lablptr+4] = (slnum >> 8) & 0xff;
}
else {
i = (symtab[lablptr + 2] << 8) +
(symtab[lablptr+1] & 0xff);
i &= 0xffff;
if (i != lval && pass == LAST_PASS) {
error("Sync error");
return(-1);
}
}
}
return(0);
}
/* determine the value of the symbol,
* given pointer to first character of symbol in symtab
*/
symval(ip)
int *ip;
{
int ptr;
int svalue;
svalue = 0;
colsym(ip);
if ((ptr = stlook()) == -1)
undef = 1; /* no room error */
else if (symtab[ptr + symtab[ptr] + 1] == UNDEF)
undef = 1;
else if (symtab[ptr + symtab[ptr] + 1] == UNDEFAB)
undef = 1;
else svalue = ((symtab[ptr + symtab[ptr] + 3] << 8) +
(symtab[ptr + symtab[ptr] + 2] & 0xff)) & 0xffff;
if (symtab[ptr + symtab[ptr] + 1] == DEFABS)
zpref = 1;
if (undef != 0)
zpref = 1;
/* add a reference entry to symbol table on first pass only,
except for branch instructions (CLASS2) which do not come
through here on the first pass */
if (ptr >= 0 && pass == FIRST_PASS) addref(ptr);
if (ptr >= 0 && opflg == CLASS2) addref(ptr); /* branch addresses */
return(svalue);
}
/* object code record generation routines */
/* added to generate MOS Technology format */
/* object records */
/* By Joel Swank 12/86 */
char obj_rec[60]; /* buffer for object record */
unsigned obj_ptr = 0; /* pointer for above */
unsigned obj_bytes = 0; /* count of bytes in current record */
unsigned rec_cnt = 0; /* count of records in this file */
unsigned cksum = 0; /* record check sum accumulator */
/* put one object byte in hex */
put_obj(val)
unsigned val;
{
hexcon(2,val);
obj_rec[obj_ptr++] = hex[1];
obj_rec[obj_ptr++] = hex[2];
cksum += (val & 0xff);
obj_bytes++;
}
/* start an object record (end previous) */
start_obj(val)
unsigned val; /* current location counter */
{
prt_obj(); /* print the current record if any */
hexcon(4,val);
obj_bytes=0;
for (obj_ptr=0; obj_ptr<4; obj_ptr++) obj_rec[obj_ptr] = hex[obj_ptr+1];
cksum = (val>>8) + (val & 0xff);
rec_cnt++;
}
/* print the current object record if any */
prt_obj()
{
if (obj_bytes == 0) return;
cksum += obj_bytes;
hexcon(2,obj_bytes);
obj_rec[obj_ptr] = '\0';
fprintf(optr,";%c%c%s",hex[1],hex[2],obj_rec);
hexcon(4,cksum);
fprintf(optr,"%c%c%c%c\n",hex[1],hex[2],hex[3],hex[4]);
}
/* finish object file */
fin_obj()
{
unsigned i;
prt_obj();
hexcon(4,++rec_cnt);
fprintf(optr,";00");
for (i=1; i<5; i++) fputc(hex[i],optr);
rec_cnt = rec_cnt/256 + (rec_cnt & 0xff);
hexcon(4,rec_cnt);
for (i=1; i<5; i++) fputc(hex[i],optr);
fputc('\n',optr);
}
/* MOS Tech. object format is as follows */
/*
( all data is in ASCII encoded hexidecimal)
Data record : ;nnaaaadddd...xxxx[cr]
Last record : ;00ccccxxxx[cr]
Where:
; = Start of record (ASCII 3B)
nn = Number of data bytes in the record.
max = 24 bytes.
aaaa = address of first data byte in the record.
dd = 1 data byte.
xxxx = checksum that is the twos compliment sum of all
data bytes, the count byte and the address bytes.
cccc = count of records in the file.
[cr] = ASCII Carriage Return (ASCII 0D).
*/